package com.hoas.databox.redis;

import com.alibaba.fastjson.JSON;
import com.hoas.databox.core.DataRepostroy;
import com.hoas.databox.core.EasyData;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.Calendar;

/**
 * Redis寄存方式，结合spring方式
 */
public class RedisDataRepostroy implements DataRepostroy {

    private JedisPool jedisPool;

    private String keyPrefix = "databox";



    public RedisDataRepostroy(String keyPrefix, JedisPool jedisPool) {
        this(jedisPool);
        this.keyPrefix = keyPrefix;
    }

    public RedisDataRepostroy(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }

    public boolean save(EasyData boxData, long second) {
        String redisKey = getKey( boxData.getNamespace(), boxData.getTicket());

        Calendar ca = Calendar.getInstance();
        ca.add(Calendar.SECOND, (int) second);
        boxData.setExpireTime(ca.getTimeInMillis());

        if (setIfAbsent( redisKey,  JSON.toJSONString( boxData ), second)){
            //请求仅一次有效（防止短时间内的重放攻击）
            return true;
        }

        return false;
    }

    public EasyData query(String namespace, String uuid, boolean multiquery) {
        String redisKey = getKey( namespace, uuid);

        String dt = getRedis( redisKey );

        if (dt == null) {
            return null;
        }

        EasyData boxData = JSON.parseObject(dt, EasyData.class);

        long curTime = System.currentTimeMillis();
        if (boxData == null || boxData.getExpireTime() <= curTime) {
            return null;
        }

        if (multiquery) {
            return boxData;
        }

        // 保证数据只能被提取一次
        if (setIfAbsent( redisKey + "_pickup", "1",  boxData.getExpireTime() - curTime)){
            //请求仅一次有效（防止短时间内的重放攻击）
            return boxData;
        }

        return null;
    }

    protected String getKey(String namespace, String uuid){
        return keyPrefix + "_" + namespace + ":" + uuid;
    }


    protected boolean setIfAbsent(final String key, final String value, final long exptime) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String result = jedis.set(key, value, "NX", "EX", exptime);;
            if ((result != null) && ("OK".equals(result) || "+OK".equals(result))){
                //请求仅一次有效（防止短时间内的重放攻击）
                return true;
            }
            return false;
        } finally {
            jedis.close();
        }

    }

    protected String getRedis(final String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.get(key);
        } finally {
            jedis.close();
        }
    }

}
